home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-20 | 33.6 KB | 1,355 lines | [TEXT/MPCC] |
- // unit WASTE3;
-
- // { WASTE PROJECT }
- // { Unit Three: Selecting; Highlighting; Scrolling &c. }
-
- // { Copyright © 1993-1994 Marco Piovanelli }
- // { All Rights Reserved }
-
- // conversion to C by Dan Crevier
-
- #include "WASTEIntf.h"
- #include <QDOffscreen.h>
-
-
- // { values for _WEArrowOffset action parameter: }
- // { plain arrow keys }
- #define kGoLeft 0
- #define kGoRight 1
- #define kGoUp 2
- #define kGoDown 3
-
- // { modifiers }
- #define kOption 4
- #define kCommand 8
-
- // { option + arrow combos }
- #define kGoWordStart kGoLeft + kOption
- #define kGoWordEnd kGoRight + kOption
- #define kGoTextStart kGoUp + kOption
- #define kGoTextEnd kGoDown + kOption
-
- // { command + arrow combos }
- #define kGoLineStart kGoLeft + kCommand
- #define kGoLineEnd kGoRight + kCommand
- #define kGoPageStart kGoUp + kCommand
- #define kGoPageEnd kGoDown + kCommand
-
-
- void ClearHiliteBit(void)
- {
- LMSetHiliteMode(LMGetHiliteMode() & 0x7f);
- }
-
- Boolean SLPixelToChar(LinePtr pLine, WERunAttributesPtr pAttrs, Ptr pSegment,
- long segmentStart, long segmentLength, JustStyleCode styleRunPosition,
- void *callbackData);
-
- Boolean SLPixelToChar(LinePtr pLine, WERunAttributesPtr pAttrs, Ptr pSegment,
- long segmentStart, long segmentLength, JustStyleCode styleRunPosition,
- void *callbackData)
- {
- struct SLPixelToCharData *p = (struct SLPixelToCharData *) callbackData;
- WEPtr pWE = p->pWE;
- Fixed slop;
- Fixed width;
- // long adjustment;
-
- // { if this is the first style run on the line, subtract pen indent from pixelWidth }
- if (styleRunPosition <= smLeftStyleRun)
- {
- // adjustment = _WECalcPenIndent(pLine->lineSlop, pWE->alignment);
- // adjustment = BSL(adjustment, 16);
- p->pixelWidth = p->pixelWidth - BSL(_WECalcPenIndent(pLine->lineSlop, pWE->alignment), 16);
- }
-
- // { strip trailing spaces if this is the last segment on the line }
- if (!(styleRunPosition & 1))
- {
- segmentLength = VisibleLength(pSegment, segmentLength);
- }
-
- // { calculate slop for this text segment (justified text only) }
- if (pWE->alignment == weJustify)
- {
- slop = FixMul(PortionLine(pSegment, segmentLength, styleRunPosition,
- *(Point *)(&kOneToOneScaling), *(Point *)(&kOneToOneScaling)),
- pLine->lineJustAmount);
- }
- else
- {
- slop = 0;
- }
-
- // { call PixelToChar for this segment }
- p->offset = segmentStart + NPixel2Char(pSegment, segmentLength, slop, p->pixelWidth,
- (Boolean *)p->edge, &width, styleRunPosition, *(Point *)(&kOneToOneScaling),
- *(Point *)(&kOneToOneScaling));
-
- // { update pixelWidth for next iteration }
- p->pixelWidth = width;
-
- // { if pixelWidth has gone negative, we're finished; otherwise go to next run }
- return (p->pixelWidth < 0);
- }
-
- pascal long WEGetOffset(LongPt *thePoint, char *edge, WEHandle hWE)
- {
- // { given a long point in local coordinates, }
- // { find the text offset corresponding to the nearest glyph }
-
- WEPtr pWE;
- long lineIndex;
- Fixed pixelWidth;
- Boolean saveWELock;
- long retval;
- struct SLPixelToCharData callbackData;
- LongPt tempPoint = *thePoint; // so we don't change original point
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { offset thePoint so that it is relative to the top left corner of the destination rectangle }
- tempPoint.v = tempPoint.v - pWE->destRect.top;
- tempPoint.h = tempPoint.h - pWE->destRect.left;
-
- // { if the point is above the destination rect, return zero }
- if (tempPoint.v < 0)
- {
- retval = 0;
- *edge = kTrailingEdge;
- }
- else
- {
- // { if the point is below the last line, return last char offset }
- if (tempPoint.v >= WEGetHeight(0, LONG_MAX, hWE))
- {
- retval = pWE->textLength;
- *edge = kLeadingEdge;
- }
- else
- {
- // { find the line index corresponding to the vertical pixel offset }
- lineIndex = _WEPixelToLine(tempPoint.v, hWE);
-
- // { express the horizontal pixel offset as a Fixed value }
- pixelWidth = BSL(tempPoint.h, 16);
-
- // { walk through the segments on this line calling PixelToChar }
- callbackData.pWE = pWE;
- callbackData.pixelWidth = pixelWidth;
- callbackData.edge = edge;
- callbackData.offset = 0;
- _WESegmentLoop(lineIndex, lineIndex, SLPixelToChar, (void *)&callbackData, hWE);
- retval = callbackData.offset;
- }
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- return retval;
- }
-
- Boolean SLCharToPixel(LinePtr pLine, WERunAttributesPtr pAttrs, Ptr pSegment,
- long segmentStart, long segmentLength, JustStyleCode styleRunPosition,
- void *callbackData);
-
- Boolean SLCharToPixel(LinePtr pLine, WERunAttributesPtr pAttrs, Ptr pSegment,
- long segmentStart, long segmentLength, JustStyleCode styleRunPosition,
- void *callbackData)
- {
- struct SLCharToPixelData *p = (struct SLCharToPixelData *) callbackData;
- WEPtr pWE = p->pWE;
- Fixed slop;
- Boolean leadingEdge;
-
- // { if this is the first style run on the line, add pen indent to thePoint.h }
- if (styleRunPosition <= smLeftStyleRun)
- {
- p->thePoint->h = p->thePoint->h + _WECalcPenIndent(pLine->lineSlop, pWE->alignment);
- }
-
- // { calculate slop for this text segment (justified text only) }
- if (pWE->alignment == weJustify)
- {
- slop = FixMul(PortionLine(pSegment, segmentLength, styleRunPosition,
- *(Point *)(&kOneToOneScaling), *(Point *)(&kOneToOneScaling)),
- pLine->lineJustAmount);
- }
- else
- {
- slop = 0;
- }
-
- // { call CharToPixel to get width of segment up to specified offset }
- leadingEdge = smHilite;
- p->thePoint->h = p->thePoint->h + NChar2Pixel(pSegment, segmentLength, slop,
- p->offset - segmentStart, smHilite, styleRunPosition,
- *(Point *)(&kOneToOneScaling), *(Point *)(&kOneToOneScaling));
-
- // { drop out of loop when we reach offset }
- return (p->offset < segmentStart + segmentLength);
- }
-
- pascal void WEGetPoint(long offset, LongPt *thePoint, short *lineHeight, WEHandle hWE)
- {
- // { given a byte offset into the text, find the corresponding glyph position }
- // { this routine is useful for highlighting the text and for positioning the caret }
-
- WEPtr pWE;
- LinePeek pLine;
- long lineIndex;
- Boolean saveWELock;
- struct SLCharToPixelData callbackData;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle) hWE, true);
- pWE = *hWE;
-
- // { the base point is the top left corner of the destination rectangle }
- *thePoint = *(LongPt *)&pWE->destRect.top;
-
- // { first of all find the line on which the glyph lies }
- lineIndex = _WEOffsetToLine(offset, hWE);
-
- // { calculate the vertical coordinate and the line height }
- pLine = (LinePeek)&((*pWE->hLines)[lineIndex]);
- thePoint->v = thePoint->v + pLine->first.lineOrigin;
- *lineHeight = pLine->second.lineOrigin - pLine->first.lineOrigin;
-
- if ((offset == pWE->textLength) && (WEGetChar(offset - 1, hWE) == '\r'))
- {
- // { SPECIAL CASE: if offset is past the last character and }
- // { the last character is a carriage return, return a point below the last line }
-
- thePoint->v = thePoint->v + *lineHeight;
- thePoint->h = thePoint->h + _WECalcPenIndent(pWE->destRect.right - pWE->destRect.left, pWE->alignment);
- }
- else
- {
- callbackData.pWE = pWE;
- callbackData.offset = offset;
- callbackData.thePoint = thePoint;
- // { to get the horizontal coordinate, walk through the style runs on this line }
- _WESegmentLoop(lineIndex, lineIndex, SLCharToPixel, (void *)&callbackData, hWE);
- }
-
- // { pin the horizontal coordinate to the destination rectangle }
- thePoint->h = _WEPinInRange(thePoint->h, pWE->destRect.left, pWE->destRect.right);
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal void WEFindLine(long offset, char edge, long *lineStart, long *lineEnd, WEHandle hWE)
- {
- WEPtr pWE;
- LineArrayPtr pLine;
-
- pWE = *hWE;
- pLine = &(*pWE->hLines)[_WEOffsetToLine(offset, hWE)];
- *lineStart = pLine[0].lineStart;
- *lineEnd = pLine[1].lineStart;
- }
-
- pascal short WEFindScriptRun(long offset, char edge, long *scriptRunStart, long *scriptRunEnd,
- WEHandle hWE)
- {
- long index, saveIndex, saveRunEnd;
- WERunInfo runInfo;
- ScriptCode script1, script2;
- short retval;
-
- if (BTST((*hWE)->flags, weFNonRoman))
- {
- // { if more than one script is installed, limit the search of script run boundaries }
- // { to a single line, for speed's sake }
- WEFindLine(offset, edge, scriptRunStart, scriptRunEnd, hWE);
-
- // { find the style run the specified offset is in }
- index = _WEOffsetToRun(offset, hWE);
- _WEGetIndStyle(index, &runInfo, hWE);
-
- // { return the style run font as function result }
- retval = runInfo.runAttrs.runStyle.tsFont;
-
- // { find the script code associated with this style run }
- script1 = Font2Script(runInfo.runAttrs.runStyle.tsFont);
-
- // { save index and runInfo.runEnd for the second while loop }
- saveIndex = index;
- saveRunEnd = runInfo.runEnd;
-
- // { walk backwards across style runs preceding offset, looking for a script run boundary }
- while (runInfo.runStart > *scriptRunStart)
- {
- index = index - 1;
- _WEGetIndStyle(index, &runInfo, hWE);
- script2 = Font2Script(runInfo.runAttrs.runStyle.tsFont);
- if (script1 != script2)
- {
- *scriptRunStart = runInfo.runEnd;
- break;
- }
- }
-
- // { restore index and runInfo.runEnd }
- index = saveIndex;
- runInfo.runEnd = saveRunEnd;
-
- // { walk forward across style runs following offset, looking for a script run boundary }
- while (runInfo.runEnd < *scriptRunEnd)
- {
- index = index + 1;
- _WEGetIndStyle(index, &runInfo, hWE);
- script2 = Font2Script(runInfo.runAttrs.runStyle.tsFont);
- if (script1 != script2)
- {
- *scriptRunEnd = runInfo.runStart;
- break;
- }
- }
- }
- else
- {
- // { only the Roman script is enabled: the whole text constitutes one script run }
- retval = systemFont;
- *scriptRunStart = 0;
- *scriptRunEnd = (*hWE)->textLength;
- }
- return retval;
- }
-
- pascal void WEFindWord(long offset, char edge, long *wordStart, long *wordEnd, WEHandle hWE)
- {
- WEPtr pWE;
- GrafPtr port, savePort;
- Handle hText;
- long runStart, runEnd;
- OffsetTable wordBreaks;
- short saveFont;
- Boolean saveTextLock;
-
- pWE = *hWE;
- port = pWE->port;
- hText = pWE->hText;
-
- // { set up the port }
- GetPort(&savePort);
- SetPort(port);
-
- // { find the script run the specified offset is in (words cannot straddle script boundaries) }
- // { and set the port font to the specified script }
- saveFont = port->txFont;
- TextFont(WEFindScriptRun(offset, edge, &runStart, &runEnd, hWE));
-
- // { make sure we pass FindWord short values }
- runStart = _WEPinInRange(runStart, offset - (SHRT_MAX / 2), offset);
- runEnd = _WEPinInRange(runEnd, offset, offset + (SHRT_MAX / 2));
-
- // { lock the text }
- saveTextLock = _WESetHandleLock(hText, true);
-
- // { call FindWord using the whole script run as a context }
- FindWord(*hText + runStart, runEnd - runStart, offset - runStart, (Boolean)edge,
- nil, wordBreaks);
-
- // { unlock the text }
- _WESetHandleLock(hText, saveTextLock);
-
- // { restore font and port }
- TextFont(saveFont);
- SetPort(savePort);
-
- // { calculate wordStart and wordEnd relative to the beginning of the text }
- *wordStart = runStart + wordBreaks[0].offFirst;
- *wordEnd = runStart + wordBreaks[0].offSecond;
- }
-
- void _WEDrawCaret(WEHandle hWE)
- {
- WEPtr pWE;
- LongPt thePoint;
- Rect caretRect;
- short caretHeight;
- GrafPtr savePort;
- RgnHandle saveClip;
-
- // { the WE record must be already locked }
- pWE = *hWE;
-
- // { do nothing if we're not active }
- if (!BTST(pWE->flags, weFActive))
- {
- return;
- }
-
- // { find the caret position using WEGetPoint }
- WEGetPoint(pWE->selStart, &thePoint, &caretHeight, hWE);
- WELongPointToPoint(&thePoint, (Point *)&caretRect.top);
- if (caretRect.left > pWE->destRect.left)
- {
- caretRect.left = caretRect.left - 1;
- }
-
- // { calculate caret rectangle }
- caretRect.bottom = caretRect.top + caretHeight;
- caretRect.right = caretRect.left + 1;
-
- // { set up the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { clip to the view region }
- saveClip = NewRgn();
- GetClip(saveClip);
- SetClip(pWE->viewRgn);
-
- // { draw the caret }
- InvertRect(&caretRect);
-
- // { invert caretVisible }
- pWE->flags = pWE->flags ^ (BSL(1, weFCaretVisible));
-
- // { update caretTime }
- pWE->caretTime = TickCount();
-
- // { restore the clip region }
- SetClip(saveClip);
- DisposeRgn(saveClip);
-
- // { restore the port }
- SetPort(savePort);
- }
-
- pascal RgnHandle WEGetHiliteRgn(long rangeStart, long rangeEnd, WEHandle hWE)
- {
- // { returns the hilite region corresponding to the specified range }
- // { the caller is responsible for disposing of the returned region }
- // { when it's finished with it }
-
- WEPtr pWE;
- RgnHandle hiliteRgn;
- LongRect selRect;
- LongPt firstPoint, lastPoint;
- short firstLineHeight, lastLineHeight;
- Rect r;
- GrafPtr savePort;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { set up the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { make sure rangeStart comes before rangeEnd }
- _WEReorder(&rangeStart, &rangeEnd);
-
- // { calculate pixel location corresponding to rangeStart }
- WEGetPoint(rangeStart, &firstPoint, &firstLineHeight, hWE);
-
- // { calculate pixel location corresponding to rangeEnd }
- WEGetPoint(rangeEnd, &lastPoint, &lastLineHeight, hWE);
-
- // { open a region: rects to be hilited will be accumulated in this }
- OpenRgn();
-
- if (firstPoint.v == lastPoint.v)
- {
- // { selection range encompasses only one line }
- WESetLongRect(&selRect, firstPoint.h, firstPoint.v, lastPoint.h, lastPoint.v + lastLineHeight);
- WELongRectToRect(&selRect, &r);
- FrameRect(&r);
- }
- else
- {
- // { selection range encompasses more than one line }
- // { hilite the first line }
- WESetLongRect(&selRect, firstPoint.h, firstPoint.v, pWE->destRect.right, firstPoint.v + firstLineHeight);
- WELongRectToRect(&selRect, &r);
- FrameRect(&r);
-
- // { any lines between the first and the last one? }
- if (firstPoint.v + firstLineHeight < lastPoint.v)
- {
- // { hilite all the lines in-between }
- WESetLongRect(&selRect, pWE->destRect.left, firstPoint.v + firstLineHeight, pWE->destRect.right, lastPoint.v);
- WELongRectToRect(&selRect, &r);
- FrameRect(&r);
- }
-
- // { hilite the last line }
- WESetLongRect(&selRect, pWE->destRect.left, lastPoint.v, lastPoint.h, lastPoint.v + lastLineHeight);
- WELongRectToRect(&selRect, &r);
- FrameRect(&r);
- }
-
- // { copy the accumulated region into a new region }
- hiliteRgn = NewRgn();
- CloseRgn(hiliteRgn);
-
- // { restrict this region to the view region }
- SectRgn(hiliteRgn, pWE->viewRgn, hiliteRgn);
-
- // { restore the port }
- SetPort(savePort);
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- // { return the hilite region }
- return hiliteRgn;
- }
-
- void _WEHiliteRange(long rangeStart, long rangeEnd, WEHandle hWE)
- {
- WEPtr pWE;
- RgnHandle saveClip, auxRgn, hiliteRgn;
- PenState savePen;
- GrafPtr savePort;
-
- // { the WE record must be already locked }
- pWE = *hWE;
-
- // { do nothing if the specified range is empty }
- if (rangeStart == rangeEnd)
- {
- return;
- }
-
- // { set up the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { create auxiliary regions }
- saveClip = NewRgn();
- auxRgn = NewRgn();
-
- // { restrict the clip region to the view rectangle }
- GetClip(saveClip);
- SectRgn(saveClip, pWE->viewRgn, auxRgn);
- SetClip(auxRgn);
-
- // { get the hilite region corresponding to the specified range }
- hiliteRgn = WEGetHiliteRgn(rangeStart, rangeEnd, hWE);
-
- // { hilite the region or frame it, depending on the setting of the active flag }
- if (BTST(pWE->flags, weFActive))
- {
- ClearHiliteBit();
- InvertRgn(hiliteRgn);
- }
- else if (BTST(pWE->flags, weFOutlineHilite))
- {
- GetPenState(&savePen);
- PenNormal();
- PenMode(patXor);
- ClearHiliteBit();
- FrameRgn(hiliteRgn);
- SetPenState(&savePen);
- }
-
- // { restore the clip region }
- SetClip(saveClip);
-
- // { dispose of all regions }
- DisposeRgn(saveClip);
- DisposeRgn(auxRgn);
- DisposeRgn(hiliteRgn);
-
- // { restore the port }
- SetPort(savePort);
- }
-
- pascal void WESetSelection(long selStart, long selEnd, WEHandle hWE)
- {
- WEPtr pWE;
- long oldSelStart, oldSelEnd;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { invalid the null style }
- BCLR(pWE->flags, weFUseNullStyle);
-
- // { hide the caret if it's showing }
- if (BTST(pWE->flags, weFCaretVisible))
- {
- _WEDrawCaret(hWE);
- }
-
- // { range-check parameters }
- selStart = _WEPinInRange(selStart, 0, pWE->textLength);
- selEnd = _WEPinInRange(selEnd, 0, pWE->textLength);
-
- // { set the weFAnchorIsEnd bit if selStart > selEnd, reorder the endpoints }
- if (selStart > selEnd)
- {
- BSET(pWE->flags, weFAnchorIsEnd);
- }
- else
- {
- BCLR(pWE->flags, weFAnchorIsEnd);
- }
- _WEReorder(&selStart, &selEnd);
-
- // { get old selection range }
- oldSelStart = pWE->selStart;
- oldSelEnd = pWE->selEnd;
-
- // { set new selection range }
- pWE->selStart = selStart;
- pWE->selEnd = selEnd;
-
- // { if we're active, invert the exclusive-OR between the old range and the new range. }
- // { if we're inactive, this optimization can't be used because of outline highlighting. }
- if (BTST(pWE->flags, weFActive))
- {
- _WEReorder(&oldSelStart, &selStart);
- _WEReorder(&oldSelEnd, &selEnd);
- _WEReorder(&oldSelEnd, &selStart);
- }
-
- _WEHiliteRange(oldSelStart, oldSelEnd, hWE);
- _WEHiliteRange(selStart, selEnd, hWE);
-
- if (!BTST(pWE->flags, weFMouseTracking))
- {
- // { redraw the caret immediately, if the selection range is empty }
- if (pWE->selStart == pWE->selEnd)
- {
- _WEDrawCaret(hWE);
- }
- // { clear clickCount, unless we're tracking the mouse }
- pWE->clickCount = 0;
-
- // { scroll the selection into view, unless we're tracking the mouse }
- WESelView(hWE);
-
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal void WEClick(Point mouseLoc, short modifiers, long clickTime, WEHandle hWE)
- {
- WEPtr pWE;
- LongPt thePoint;
- long offset, anchor;
- long rangeStart, rangeEnd;
- char edge;
- Boolean isMultipleClick;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { hide the caret if it's showing }
- if (BTST(pWE->flags, weFCaretVisible))
- {
- _WEDrawCaret(hWE);
- }
-
- // { find click offset }
- WEPointToLongPoint(mouseLoc, &thePoint);
- offset = WEGetOffset(&thePoint, &edge, hWE);
-
- // { determine whether this click is part of a sequence }
- isMultipleClick = ((clickTime < pWE->clickTime + GetDblTime()) &&
- (offset == pWE->clickLoc));
-
- // { remember click time, click offset and edge value }
- pWE->clickTime = clickTime;
- pWE->clickLoc = offset;
- pWE->clickEdge = edge;
-
- if ((modifiers & shiftKey) == 0)
- {
- // { is this click part of a sequence or is it an isolate click? }
- if (isMultipleClick)
- {
- pWE->clickCount = pWE->clickCount + 1;
- // { a double (triple) click creates an anchor-word (anchor-line) }
- if (pWE->clickCount > 1)
- {
- WEFindLine(offset, edge, &pWE->anchorStart, &pWE->anchorEnd, hWE);
- }
- else
- {
- WEFindWord(offset, edge, &pWE->anchorStart, &pWE->anchorEnd, hWE);
- }
- offset = pWE->anchorStart;
- }
- else
- {
- pWE->clickCount = 0;
- anchor = offset;
- }
- }
- else
- {
- // { if the shift key was down, use the old anchor offset found with the previous click }
- if (BTST(pWE->flags, weFAnchorIsEnd))
- {
- anchor = pWE->selEnd;
- }
- else
- {
- anchor = pWE->selStart;
- }
- }
-
- // { set the weFMouseTracking bit while we track the mouse }
- BSET(pWE->flags, weFMouseTracking);
-
- // { MOUSE TRACKING LOOP }
- do
- {
- // { get text offset corresponding to mouse position }
- WEPointToLongPoint(mouseLoc, &thePoint);
- offset = WEGetOffset(&thePoint, &edge, hWE);
-
- // { if we're selecting words or lines, pin offset to a word or line boundary }
- if (pWE->clickCount > 0)
- {
- if (pWE->clickCount > 1)
- {
- WEFindLine(offset, edge, &rangeStart, &rangeEnd, hWE);
- }
- else
- {
- WEFindWord(offset, edge, &rangeStart, &rangeEnd, hWE);
- }
- // { choose the word/line boundary and the anchor that are farthest away from each other }
- if (offset > pWE->anchorStart)
- {
- anchor = pWE->anchorStart;
- offset = rangeEnd;
- }
- else
- {
- offset = rangeStart;
- anchor = pWE->anchorEnd;
- }
- }
- // { set the selection range from anchor point to current offset }
- WESetSelection(anchor, offset, hWE);
-
- // { call the click loop callback, if any }
- if (pWE->clickLoop != nil)
- {
- if (((WEClickLoopProcPtr)pWE->clickLoop)(hWE) == false)
- {
- break;
- }
- }
- // { update mouse position }
- GetMouse(&mouseLoc);
- } while (WaitMouseUp());
-
- // { clear the weFMouseTracking bit }
- BCLR(pWE->flags, weFMouseTracking);
-
- // { redraw the caret immediately if the selection range is empty }
- if (anchor == offset)
- {
- _WEDrawCaret(hWE);
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal void WESetAlignment(char alignment, WEHandle hWE)
- {
- if ((alignment >= weFlushLeft) && (alignment <= weJustify))
- {
- if (alignment != (*hWE)->alignment)
- {
- (*hWE)->alignment = alignment;
- WEUpdate(nil, hWE);
- }
- }
- }
-
- long _WEArrowOffset(short action, long offset, WEHandle hWE)
- {
- // { given an action code (corresponding to a modifiers + arrow key combo) }
- // { and an offset into the text, find the offset of the new caret position }
-
- LongPt thePoint;
- long textLength, rangeStart, rangeEnd;
- short lineHeight;
- char edge;
-
- textLength = (*hWE)->textLength;
- switch (action)
- {
- case kGoLeft:
- if (offset > 0)
- {
- offset = offset - 1;
- if (WECharByte(offset, hWE) != smSingleByte)
- {
- offset = offset - 1;
- }
- }
- break;
-
- case kGoRight:
- if (offset < textLength)
- {
- offset = offset + 1;
- if (WECharByte(offset, hWE) != smSingleByte)
- {
- offset = offset + 1;
- }
- }
- break;
-
- case kGoUp:
- WEGetPoint(offset, &thePoint, &lineHeight, hWE);
- thePoint.v = thePoint.v - 1;
- offset = WEGetOffset(&thePoint, &edge, hWE);
- break;
-
- case kGoDown:
- WEGetPoint(offset, &thePoint, &lineHeight, hWE);
- thePoint.v = thePoint.v + lineHeight;
- offset = WEGetOffset(&thePoint, &edge, hWE);
- break;
-
- case kGoWordStart:
- WEFindWord(offset, kTrailingEdge, &rangeStart, &rangeEnd, hWE);
- offset = rangeStart;
- break;
-
- case kGoWordEnd:
- WEFindWord(offset, kLeadingEdge, &rangeStart, &rangeEnd, hWE);
- offset = rangeEnd;
- break;
-
- case kGoTextStart:
- offset = 0;
- break;
-
- case kGoTextEnd:
- offset = textLength;
- break;
-
- case kGoLineStart:
- WEFindLine(offset, kLeadingEdge, &rangeStart, &rangeEnd, hWE);
- offset = rangeStart;
- break;
-
- case kGoLineEnd:
- WEFindLine(offset, kTrailingEdge, &rangeStart, &rangeEnd, hWE);
- offset = rangeEnd;
- if (offset < textLength)
- {
- offset = offset - 1;
- if (WECharByte(offset, hWE) != smSingleByte)
- {
- offset = offset - 1;
- }
- }
- break;
-
- default:
- break;
- }
-
- return offset;
- }
-
- void _WEDoArrowKey (short arrow, short modifiers, WEHandle hWE)
- {
- // { this routine is called by WEKey to handle arrow keys }
- // { the WE record is guaranteed to be already locked }
-
- WEPtr pWE;
- short action;
- long selStart, selEnd;
- long caretLoc, anchor;
-
- pWE = *hWE;
-
- // { calculate the "action" parameter for _WEArrowOffset from arrow and modifiers }
- action = arrow - kArrowLeft; // { possible range: 0..3 }
- if (modifiers & optionKey)
- {
- action = action + kOption;
- }
- if (modifiers & cmdKey)
- {
- action = action + kCommand;
- }
-
- // { get selection range }
- selStart = pWE->selStart;
- selEnd = pWE->selEnd;
-
- if ((modifiers & shiftKey) == 0)
- {
- // { if selection range isn't empty, collapse it to one of the endpoints }
- if (selStart < selEnd)
- {
- if ((arrow == kArrowLeft) || (arrow == kArrowUp))
- {
- caretLoc = selStart;
- }
- else
- {
- caretLoc = selEnd;
- }
- }
- else
- {
- // { otherwise move the insertion point }
- caretLoc = _WEArrowOffset(action, selStart, hWE);
- }
-
- // { set anchor to caretLoc, so new selection will be empty }
- anchor = caretLoc;
- }
- else
- {
- // { shift key was held down: extend the selection rather than replacing it }
- // { find out which selection boundary is the anchor and which is the free endpoint }
- if (BTST(pWE->flags, weFAnchorIsEnd))
- {
- anchor = selEnd;
- caretLoc = selStart;
- }
- else
- {
- anchor = selStart;
- caretLoc = selEnd;
- }
-
- // { move the free endpoint }
- caretLoc = _WEArrowOffset(action, caretLoc, hWE);
- }
-
- // { select the new selection }
- WESetSelection(anchor, caretLoc, hWE);
- }
-
- pascal Boolean WEAdjustCursor(Point mouseLoc, RgnHandle mouseRgn, WEHandle hWE)
- {
- // { Call WEAdjustCursor to set the cursor shape when the mouse is in the view rectangle. }
- // { MouseRgn should be either a valid region handle or NIL. }
- // { If mouseRgn is supplied (i.e., if it's not NIL), it is intersected with a region }
- // { in global coordinates within which the cursor is to retain its shape. }
- // { WEAdjustCursor returns TRUE if the cursor has been set. }
- // { Your application should set the cursor only if WEAdjustCursor returns FALSE. }
-
- WEPtr pWE;
- RgnHandle auxRgn;
- Point portDelta;
- GrafPtr savePort;
- Boolean saveWELock;
- Boolean adjustCursor;
- Point zeroPoint = {0, 0};
-
- adjustCursor = false;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { set up the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { calculate delta between the local coordinate system and the global one }
- portDelta = zeroPoint;
- LocalToGlobal(&portDelta);
-
- // { calculate the visible portion of the view rectangle, in global coordinates }
- auxRgn = NewRgn();
- CopyRgn(pWE->viewRgn, auxRgn);
- SectRgn(auxRgn, pWE->port->visRgn, auxRgn);
- OffsetRgn(auxRgn, portDelta.h, portDelta.v);
-
- if (PtInRgn(mouseLoc, auxRgn))
- {
- // { mouse is within view rectangle: it's up to us to set the cursor }
- adjustCursor = true;
-
- // { set the cursor to an I-beam }
- SetCursor(*GetCursor(iBeamCursor));
-
- // { set mouseRgn, if provided }
- if (mouseRgn != nil)
- {
- SectRgn(mouseRgn, auxRgn, mouseRgn);
- }
- }
- else
- {
- // { mouse is outside view rectangle: don't set the cursor; subtract viewRgn from mouseRgn }
- if (mouseRgn != nil)
- {
- DiffRgn(mouseRgn, auxRgn, mouseRgn);
- }
- }
- // { dispose of the temporary region }
- DisposeRgn(auxRgn);
-
- // { restore the port }
- SetPort(savePort);
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- return adjustCursor;
- }
-
- pascal void WEIdle(long *maxSleep, WEHandle hWE)
- {
- WEPtr pWE;
- long caretInterval, sleepTime;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { the caret blinks only if we're active and the selection point is empty }
- if (BTST(pWE->flags, weFActive) && (pWE->selStart == pWE->selEnd))
- {
- // { the low-memory global variable CaretTime contains the preferred interval }
- // { between successive inversions of the caret }
- caretInterval = GetCaretTime();
-
- // { calculate how many ticks we can sleep before we need to invert the caret }
- // { the caretTime field of the WE record contains the time of the last inversion }
- sleepTime = caretInterval - (TickCount() - pWE->caretTime);
-
- // { if sleepTime has gone negative, invert the caret }
- if (sleepTime <= 0)
- {
- _WEDrawCaret(hWE);
- sleepTime = caretInterval;
- }
- }
- else
- {
- // { if we don't need to blink the caret, we can sleep forever }
- sleepTime = LONG_MAX;
- }
-
- // { return sleepTime to the caller if maxSleep isn't NIL }
- if (maxSleep != nil)
- {
- *maxSleep = sleepTime;
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal void WEUpdate(RgnHandle updateRgn, WEHandle hWE)
- {
- WEPtr pWE;
- long firstLine, lastLine;
- Rect auxRect;
- RgnHandle saveClip, auxRgn;
- GrafPtr savePort;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { set up the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { save the clip region }
- saveClip = NewRgn();
- GetClip(saveClip);
-
- // { clip to the insersection between updateRgn and the view rectangle }
- // { (updateRgn may be NIL; in this case, just clip to the view rectangle) }
- auxRgn = NewRgn();
- if (updateRgn != nil)
- {
- SectRgn(updateRgn, pWE->viewRgn, auxRgn);
- }
- else
- {
- CopyRgn(pWE->viewRgn, auxRgn);
- }
- SetClip(auxRgn);
-
- if (EmptyRgn(auxRgn) == false)
- {
- // { set auxRect to the bounding box of the update region (clipped to the view rectangle) }
- auxRect = (*auxRgn)->rgnBBox;
-
- // { find out which lines need to be redrawn }
- firstLine = _WEPixelToLine(auxRect.top - pWE->destRect.top, hWE);
- lastLine = _WEPixelToLine((auxRect.bottom - 1) - pWE->destRect.top, hWE);
-
- // { draw them (if updateRgn is NIL, erase each line rectangle before redrawing) }
- _WEDrawLines(firstLine, lastLine, (updateRgn == nil), hWE);
-
- // { hilite the selection range or draw the caret (only if active) }
- if (pWE->selStart < pWE->selEnd)
- _WEHiliteRange(pWE->selStart, pWE->selEnd, hWE);
- else if (BTST(pWE->flags, weFCaretVisible))
- {
- _WEDrawCaret(hWE);
- BSET(pWE->flags, weFCaretVisible);
- }
- }
-
- DisposeRgn(auxRgn);
-
- // { restore the clip region }
- SetClip(saveClip);
- DisposeRgn(saveClip);
-
- // { restore the port }
- SetPort(savePort);
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal void WEDeactivate(WEHandle hWE)
- {
- WEPtr pWE;
- Boolean saveWELock;
-
- if (!WEIsActive(hWE)) return;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { hide the selection range or the caret }
- _WEHiliteRange(pWE->selStart, pWE->selEnd, hWE);
- if (BTST(pWE->flags, weFCaretVisible))
- {
- _WEDrawCaret(hWE);
- }
-
- // { clear the active flag }
- BCLR(pWE->flags, weFActive);
-
- // { frame the selection }
- _WEHiliteRange(pWE->selStart, pWE->selEnd, hWE);
-
- // { dispose of the offscreen graphics world, if any }
- if (pWE->offscreenPort != nil)
- {
- DisposeGWorld((GWorldPtr)(pWE->offscreenPort));
- pWE->offscreenPort = nil;
- }
-
- // { notify Text Services }
- if (pWE->tsmReference != nil)
- {
- DeactivateTSMDocument(pWE->tsmReference);
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal void WEActivate(WEHandle hWE)
- {
- WEPtr pWE;
- Boolean saveWELock;
-
- if (WEIsActive(hWE)) return;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { remove the selection frame }
- _WEHiliteRange(pWE->selStart, pWE->selEnd, hWE);
-
- // { set the active flag }
- BSET(pWE->flags, weFActive);
-
- // { show the selection range }
- _WEHiliteRange(pWE->selStart, pWE->selEnd, hWE);
-
- // { notify Text Services }
- if (pWE->tsmReference != nil)
- {
- ActivateTSMDocument(pWE->tsmReference);
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal Boolean WEIsActive(WEHandle hWE)
- {
- // { return TRUE iff the specified WE instance is currently active }
- return BTST((*hWE)->flags, weFActive);
- }
-
- pascal void WEScroll(long hOffset, long vOffset, WEHandle hWE)
- {
- WEPtr pWE;
- Rect viewRect;
- RgnHandle updateRgn;
- GrafPtr savePort;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { hide the caret if it's showing }
- if (BTST(pWE->flags, weFCaretVisible))
- {
- _WEDrawCaret(hWE);
- }
-
- // { offset the destination rectangle by the specified amount }
- WEOffsetLongRect(&pWE->destRect, hOffset, vOffset);
-
- // { set up the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- viewRect = (*pWE->viewRgn)->rgnBBox;
- updateRgn = NewRgn();
-
- // { scroll the view rectangle }
- ScrollRect(&viewRect, hOffset, vOffset, updateRgn);
-
- // { redraw the exposed region }
- WEUpdate(updateRgn, hWE);
- DisposeRgn(updateRgn);
-
- // { restore the port }
- SetPort(savePort);
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- Boolean _WEScrollIntoView (long offset, WEHandle hWE)
- {
- WEPtr pWE;
- LongPt thePoint;
- short lineHeight;
- long hScroll, vScroll, temp;
- Boolean retval;
-
- pWE = *hWE;
-
- // { do nothing if automatic scrolling is disabled }
- if (!BTST(pWE->flags, weFAutoScroll))
- {
- return false;
- }
-
- // { find the selection point }
- WEGetPoint(offset, &thePoint, &lineHeight, hWE);
-
- // { assume no scrolling is needed }
- retval = false;
- vScroll = 0;
- hScroll = 0;
-
- // { determine if we need to scroll vertically }
- if ((thePoint.v < pWE->viewRect.top) ||
- (thePoint.v + lineHeight >= pWE->viewRect.bottom))
- {
- // { calculate the amount of vertical scrolling needed to center the selection into view }
- vScroll = BSR(pWE->viewRect.top + pWE->viewRect.bottom, 1) - thePoint.v;
-
- // { we'd like to superimpose the bottom margins of the dest/view rects, if possible }
- temp = pWE->viewRect.bottom - pWE->destRect.bottom;
- if (temp > vScroll)
- {
- vScroll = temp;
- }
- // { but we also have to make sure the dest top isn't scrolled below the view top }
- temp = pWE->viewRect.top - pWE->destRect.top;
- if (temp < vScroll)
- {
- vScroll = temp;
- }
- }
-
- // { determine if we need to scroll horizontally }
- if ((thePoint.h - 1 < pWE->viewRect.left) || (thePoint.h >= pWE->viewRect.right))
- {
- // { calculate the amount of horizontal scrolling needed to center the selection into view }
- hScroll = BSR(pWE->viewRect.left + pWE->viewRect.right, 1) - thePoint.h;
-
- // { we'd like to superimpose the right margins of the dest/view rects, if possible }
- temp = pWE->viewRect.right - pWE->destRect.right;
- if (temp > hScroll)
- {
- hScroll = temp;
- }
-
- // { but we also have to make sure the dest left isn't scrolled to the right of the view left }
- temp = pWE->viewRect.left - pWE->destRect.left;
- if (temp < hScroll)
- {
- hScroll = temp;
- }
- }
-
- // { scroll the text if necessary }
- if ((vScroll != 0) || (hScroll != 0))
- {
- retval = true;
- WEScroll(hScroll, vScroll, hWE);
- }
-
- // { call the scroll callback, if any }
- if (pWE->scrollProc != nil)
- {
- ((WEScrollProcPtr)pWE->scrollProc)(hWE);
- }
- return retval;
- }
-
- pascal void WESelView(WEHandle hWE)
- {
- WEPtr pWE;
- long offset;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { scroll the free endpoint of the selection into view }
- if (BTST(pWE->flags, weFAnchorIsEnd))
- {
- offset = pWE->selStart;
- }
- else
- {
- offset = pWE->selEnd;
- }
- _WEScrollIntoView(offset, hWE);
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-